package com.flyiu.data.face;

import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.util.Assert;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;

/**
 * json 扁平化
 * 
 * @author chenjh
 *
 */
public class JsonFlat {

	/** 解析器 */
	private JsonParser parser = new JsonParser();

	/** 遍历尝试 */
	private int maxDeep = 3;

	/** GSON线程安全 */
	private JsonObject newjosnObject = new JsonObject();

	/**
	 * 无参构造方法
	 */
	public JsonFlat() {
		super();
	}

	/**
	 * 外部设置
	 * 
	 * @param parser
	 * @param maxDeep
	 */
	public JsonFlat(JsonParser parser, int maxDeep) {
		super();
		if (parser != null) {
			this.parser = parser;
		}
		Assert.isTrue(maxDeep > 0, "maxDeep 必须大于0");
		this.maxDeep = maxDeep;
	}

	/**
	 * 解析json对象
	 * 
	 * @param jsonStr
	 * @return
	 */
	public JsonObject parse(String jsonStr) {

		try {
			parser.parse(jsonStr);
		} catch (JsonSyntaxException e) {
			throw new RuntimeException("解析json失败，请检查输入", e);
		}
		JsonElement rootElement = parser.parse(jsonStr);
		parse("", rootElement, newjosnObject, 1);
		return newjosnObject;
	}

	/**
	 * json对象展开。如遇到节点为json或数组时进行递归处理。 暂不进行深度考虑，暂不进行数组中值为json的情况处理
	 * 
	 * @param parentName
	 *            父节点名称
	 * @param json
	 *            json对象
	 * @param newjosnObject
	 *            用于返回的json对象
	 * @param deep
	 *            深度
	 */
	private void parse(String parentName, JsonElement json, JsonObject newjosnObject, int deep) {
		if (deep > maxDeep) {
			throw new RuntimeException("json对象深度超过最大允许深度");
		}

		if (json.isJsonArray()) { // 数组处理
			newjosnObject.add(parentName, json);
			return;
		}

		JsonObject josnObject = json.getAsJsonObject();
		Set<Entry<String, JsonElement>> jsonSet = josnObject.entrySet();
		for (Iterator iterator = jsonSet.iterator(); iterator.hasNext();) {
			Entry<String, JsonElement> entry = (Entry<String, JsonElement>) iterator.next();
			String key = entry.getKey();
			JsonElement element = entry.getValue();

			if (element.isJsonArray() || element.isJsonObject()) {
				parse(parentName + key + ".", element, newjosnObject, deep + 1);
			} else {
				newjosnObject.add(parentName + key, element);
			}

		}

	}

	public JsonParser getParser() {
		return parser;
	}

	public void setParser(JsonParser parser) {
		this.parser = parser;
	}

	public int getMaxDeep() {
		return maxDeep;
	}

	public void setMaxDeep(int maxDeep) {
		this.maxDeep = maxDeep;
	}

	public static void main(String[] args) {
		JsonFlat flat = new JsonFlat();
		String jsonStr = "{ \"a\": null, \"b\": { \"c\": 2, \"d\": [3,4] } }";
		JsonObject jsonObject = flat.parse(jsonStr);
		System.out.println(jsonObject);
	}

}
